<?php

namespace app\common\logic;

use app\common\library\exception\ApiException;
use app\common\library\Helper\DateTime;
use app\common\library\MemberVo;
use app\common\model\Car;
use app\common\model\Member;
use app\common\model\MoneyRecord;
use app\common\model\Order;
use app\common\model\OrderGoods;
use app\common\model\PayLog;
use app\common\model\Recharge;
use app\common\model\RechargeTemplate;
use app\common\model\Shop;
use app\common\resourceHandle\OrderResource;
use EasyWeChat\Factory;
use think\Db;
use think\db\Query;
use think\Env;
use think\Exception;
use think\Log;
use Wxcrypt\XcxPay;

class MoneyRecordLogic extends BaseLogic
{
    public $model;

    public $orderResourceHandle;

    public function assignModel()
    {
        $this->model               = new MoneyRecord();
        $this->orderResourceHandle = new OrderResource();
    }

    /**
     * 搜索条件处理
     * @param Query $query
     * @param array $params
     * @return Query
     */
    public function handleSearch(Query $query, array $params): Query
    {
        if(isset($params['date_time']) && !empty($params['date_time'])) {
            $timeZone = DateTime::toTimestamp('rangeMonthByDate', $params['date_time']);
            $query->whereBetween('fa_money_record.createtime', $timeZone);
        }
        if(isset($params['type']) && !empty($params['type'])) {
            $query->where('fa_money_record.type', $params['type']);
        }
//        if(isset($params['detail_type']) && !empty($params['detail_type'])) {
//            $query->where('fa_money_record.detail_type', $params['detail_type']);
//        }

        if(isset($params['detail_type']) && !empty($params['detail_type'])) {
            $query->whereIn('fa_money_record.detail_type', $params['detail_type']);
        }


        if(isset($params['member_id'])) {
            $query->where('fa_money_record.member_id', $params['member_id']);
        }
        if(isset($params['agent_id'])) {
            $query->where('fa_money_record.agent_id', $params['agent_id']);
        }
        if(isset($params['shop_id'])) {
            $query->where('fa_money_record.shop_id', $params['shop_id']);
        }

        if(isset($params['shop_detail_type']) && !empty($params['shop_detail_type'])) {
            $query->whereIn("fa_money_record.detail_type",[1,4]);
        }

        return $query;
    }


    /**
     * 获取商家资金明细
     * @param $params
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public function index($params){
        $params['shop_id'] = MemberVo::instance()->getShopId();
        $params['member_id'] =0;
        $params['agent_id'] = 0;
        $params['shop_detail_type'] = 1;
        $params['orderBy'] = 'fa_money_record.id';
        $params['orderType'] = 'desc';
        $params['field'] = ['type','detail_type','money','balance','remark','createtime'];
        return $this->getPageList($params);


    }

    /**
     * 获取状态正常的模版
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getRechargeTemplate()
    {
        return RechargeTemplate::getStatusOnTemplate()->toArray();
    }

    /**
     * 充值
     * @param array $params
     * @return array|false|string
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function recharge(array $params)
    {
        $template = RechargeTemplate::find($params['template_id']);
        if(empty($template))
            throw new ApiException('充值模版错误',404);
        $wechat   = Factory::payment(config('wechat.payment'));
        $order    = [
            'order_sn'   => 'RCG' . Order::generateOrderSn(),
            'pay_amount' => (int)bcmul($template['recharge_money'], '100', 2),
            'openid'     => $this->openid,
            'member_id'  => $this->memberId,
            'shop_id'    => 0,
            'recharge_id'   => $template['id']
        ];
        $result   = $wechat->order->unify([
            'body'         => '洗车小程序-充值',
            'out_trade_no' => $order['order_sn'],
            'total_fee'    => $order['pay_amount'],
            'notify_url'   => Env::get('app.app_host') . '/index/wechat/recharge_notify',
            'trade_type'   => 'JSAPI',
            'openid'       => $this->openid,
        ]);
        if ($result['return_code'] === 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            PayLog::rechargePayCreate($order);
            return $wechat->jssdk->bridgeConfig($result['prepay_id'], false);
        } else {
            return false;
        }
    }


    /**提现申请
     * @param array $params
     * @return bool
     */
    public function withdrawal(array $params)
    {
        Db::startTrans();
        try{
            //查看金额
            $memberInfo = Member::get(['id'=>$params['member_id']]);
            if ($memberInfo->balance < $params['money'])
                throw new Exception('提现金额不能大于当前余额',404);
            $memberInfo->balance = bcsub($memberInfo->balance ,$params['money'],2);
            $memberInfo->save();
            $res = MoneyRecord::create(['type'=>2,'detail_type'=>2,'money'=>$params['money'],'balance'=>$memberInfo->balance,'member_id'=>$params['member_id'],'tx_status'=>1,'remark'=>'微信转账中']);
            // 发起微信转账申请
            $xccPay = new XcxPay();
            $result = $xccPay->transfer_batches($memberInfo->mini_openid,$params['money']);
            if (isset($result['code']))
                throw new Exception('申请提现失败：'.$result['message']);
            $res->batch_id = $result['batch_id'];
            $res->out_batch_no = $result['out_batch_no'];
            $res->remark = '微信转账中';
            $res->save();
            Db::commit();
            return true;
        }catch (Exception $e){
            Db::rollback();
            throw new ApiException($e->getMessage(),404);
        }

    }

    /**
     * 客户充值回调
     * @return \Symfony\Component\HttpFoundation\Response
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    public function rechargeNotify()
    {
        $wechat = Factory::payment(config('wechat.payment'));
        return $wechat->handlePaidNotify(function ($message, $fail) use ($wechat) {
            Db::startTrans();
            try {
                $date = date('Ymd');
                $fp   = fopen(RUNTIME_PATH . "/log/log_order_notify-{$date}.php", "a");
                fwrite($fp, date('Y-m-d H:i:s') . "   " . json_encode($message) . "\r\n");
                fclose($fp);

                $payOrder = PayLog::where('order_sn', $message['out_trade_no'])->find();
                if (empty($payOrder) || $payOrder['status'] !== 1) {
                    return true;
                }

                if ($message['return_code'] === 'SUCCESS' && $message['result_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态

                    // 再查一次微信订单确保安全
                    $res = $wechat->order->queryByOutTradeNumber($message['out_trade_no']);

                    if ($res['return_code'] === 'SUCCESS' && $res['result_code'] === 'SUCCESS' && $res['trade_state'] === 'SUCCESS') {
                        bcscale(2);
                        // 会员收支记录
                        MoneyRecord::create([ // 充值记录
                            'member_id'   => $payOrder['member_id'],
                            'type'        => MoneyRecord::TYPE_INCOME,
                            'money'       => $payOrder['pay_amount'],
                            'balance'     => model('member')->where('id', $payOrder['member_id'])->value('balance') ?? 0,
                            'detail_type' => MoneyRecord::DETAIL_TYPE_RECHARGE,
                            'remark'      => '微信充值',
                        ]);
                        PayLog::payFinish($res);
                        if($payOrder['give_money'] > 0) {
                            MoneyRecord::create([ // 赠送记录
                                'member_id'   => $payOrder['member_id'],
                                'type'        => MoneyRecord::TYPE_INCOME,
                                'money'       => $payOrder['give_money'],
                                'balance'     => model('member')->where('id', $payOrder['member_id'])->value('balance') ?? 0,
                                'detail_type' => MoneyRecord::DETAIL_TYPE_GIVING,
                                'remark'      => '微信充值赠送',
                            ]);
                        }
                        // 修改会员折扣
                        $member = Member::get($payOrder['member_id']);
                        if(bccomp($member['discount'], $payOrder['discount']) === 1) {
                            $member->disount = $payOrder['discount'];
                        }
                        // 增加会员余额
                        $member->balance = bcadd($member->balance, bcadd($payOrder['pay_amount'], $payOrder['give_money']));
                        $member->save();
                    }

                } else {
                    return $fail('通信失败，请稍后再通知我');
                }
                Db::commit();
                return true;
            } catch (Exception $e) {
                Db::rollback();
                Log::error('支付回调处理失败' . $e->getMessage());
                return false;
            }
        });
    }

    /**
     * 会员消费记录
     * @param array $params
     * @return array
     * @throws \think\exception\DbException
     */
    public function memberConsumeRecord($params)
    {
        Member::update(['balance_show_drop'=>0],['id'=>MemberVo::instance()->getMemberId()]);
        $list = ['list'=>[],'all_money'=>'0.00'];
        $params['type'] = MoneyRecord::TYPE_SPEND;//收入
        $params['detail_type'] = [MoneyRecord::DETAIL_TYPE_ORDER];//订单
        $params['member_id'] = $this->memberId;//用户id
        $params['with'] = ['orders'];
        $params['orderBy'] = 'money_record.id';
        $params['orderType'] = 'desc';
        $list['list'] = $this->getList($params)->each(function (&$item){
            $item['shop_name'] = Shop::where('id',$item['orders']['shop_id'])->value('shop_name');
            $item['car_numbers'] = Car::where('id',$item['orders']['car_id'])->value('car_numbers');
            $item['goods'] = OrderGoods::where('order_id',$item['orders']['id'])->field('goods_name,goods_num')->select();
            unset($item['orders']);
            return $item;
        })->toArray();
        if (!empty($list['list'])){
            $list['all_money'] = sprintf("%.2f",substr(sprintf("%.3f", array_sum(array_column($list['list'],'money'))), 0, -1));
        }
        return $list;
    }

    /**
     * 会员充值记录
     * @return array
     * @throws \think\exception\DbException
     */
    public function memberRechargeRecord($params)
    {
        $list = ['list'=>[],'all_money'=>'0.00'];
//        $params['type'] = MoneyRecord::TYPE_INCOME;//收入
        $params['detail_type'] = [MoneyRecord::DETAIL_TYPE_RECHARGE,MoneyRecord::DETAIL_TYPE_TXREFUND,MoneyRecord::DETAIL_TYPE_WITHDRAW];//充值
        $params['member_id'] = $this->memberId;//用户id
        $list['list'] = $this->getList($params)->toArray();
        $list['all_money'] = 0;
        if (!empty($list['list'])){
            foreach ($list['list'] as &$v){
                if ($v['detail_type'] == MoneyRecord::DETAIL_TYPE_RECHARGE ){
                    $v['money_new'] = '+'.$v['money'];
                    $v['tip'] = '充值';
                    $list['all_money'] = bcadd($list['all_money'],$v['money'],2);
                }elseif ($v['detail_type'] == MoneyRecord::DETAIL_TYPE_TXREFUND ){
                    $v['money_new'] = '+'.$v['money'];
                    $v['tip'] = '提现失败，退回！';
                    $list['all_money'] = bcadd($list['all_money'],$v['money'],2);
                }else{
                    $v['money_new'] = '-'.$v['money'];
                    $v['tip'] = '提现';
                    $list['all_money'] = bcsub($list['all_money'],$v['money'],2);
                }

            }
//            $list['all_money'] = sprintf("%.2f",substr(sprintf("%.3f", array_sum(array_column($list['list'],'money'))), 0, -1));
        }

        return $list;
    }

    /**
     * 商家消费记录
     * @param array $params
     * @return array
     * @throws \think\exception\DbException
     */
    public function shopConsumeRecord(array $params = [])
    {
        $timeZone = [];
        if(isset($params['date_time']) && !empty($params['date_time'])) {
            $timeZone = DateTime::toTimestamp('rangeMonthByDate', $params['date_time']);
        }
        $list =  Order::shopOrderPayRecord($this->shopId, function ($query) use ($timeZone,$params) {
            if(!empty($timeZone)) {
                $query->whereBetween('audit_time', $timeZone);
            }
            if (isset($params['goods_id']) && !empty($params['goods_id'])) {
                $orderIds = OrderGoods::where(['goods_id'=>$params['goods_id'],'shop_id'=>$this->shopId])->column('order_id');
                $query->whereIN('order.id', $orderIds);
            }
            if (isset($params['keyword']) && !empty($params['keyword'])) {
                $whereOrRaw = "car.car_numbers LIKE '%{$params['keyword']}%' or order.order_sn LIKE '%{$params['keyword']}%'";
                $query->where($whereOrRaw);
            }

        })->toArray();
        foreach ($list['data'] as &$item){
            //获取车辆
            $car_info = Car::get($item['car']['id'],['brand','series']);
            $arr = [
                'id'=>$item['id'],
                'order_sn'=>$item['order_sn'],
                'member_name'=>$item['member']['member_name'],
                'member_mobile'=>$item['member']['member_mobile'],
                'car_numbers'=>$item['car']['car_numbers'],
                'goods_name'=>empty($item['order_goods']) ? '' : $item['order_goods'][0]['goods_name'],
                'order_amount'=>$item['order_amount'],
                'audit_time'=>$item['audit_time'],
                'car_brand'=>$car_info['brand']['name'] ?? '',
                'car_series'=>$car_info['series']['name'] ?? '',
                ];
            $item = $arr;
        }
        return $list;
    }

    /**
     * 商家充值记录
     * @param array $params
     * @return array
     * @throws \think\exception\DbException
     */
    public function shopRechargeRecord(array $params = [])
    {
        $timeZone = [];
        if(isset($params['date_time'])) {
            $timeZone = DateTime::toTimestamp('rangeMonthByDate', $params['date_time']);
        }
        $recordList = Recharge::shopRechargeRecord($this->shopId, function ($query) use ($timeZone) {
            if(!empty($timeZone)) {
                $query->whereBetween('createtime', $timeZone);
            }
        });
        foreach ($recordList as $list) {
            if(!empty($list->agent)) {
                $list->agent->visible(['username']);
                $list->createtime = date('Y-m-d H:i:s', $list->createtime);
            }
        }
        return [$recordList->items(), $this->generateMeta($recordList)];
    }

}